﻿// *----------------------------------------------------------------
// Copyright (C) 2017 通通优品
// 版权所有。
// 
// 类名：DefaultModuleFinder.cs
// 功能描述：TongTongMall
// 
// Create User：jym 2017/02/09
// 
// Edit User：UserName,EditTime
// Describe：Describe
// ----------------------------------------------------------------*/
using Castle.Core.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using TongTongMall.Collections.Extensions;
using TongTongMall.Reflection;

namespace TongTongMall.Modules
{
    internal class DefaultModuleFinder : IModuleFinder
    {

        public ILogger Logger { get; set; }
        public IAssemblyFinder AssemblyFinder { get; set; }
        public DefaultModuleFinder(IAssemblyFinder AssemblyFinder)
        {
            this.AssemblyFinder = AssemblyFinder;

            Logger = NullLogger.Instance;
        }

        public ICollection<Type> FindAll()
        {
            return GetAllTypes().Where(BaseModule.IsBaseModule).ToArray();
        }

        public Type[] Find(Func<Type, bool> predicate)
        {
            return GetAllTypes().Where(predicate).ToArray();
        }

        private List<Type> GetAllTypes() 
        {
            var allTypes = new List<Type>();

            foreach (var assembly in AssemblyFinder.GetAllAssemblies())
            {
                try
                {
                    Type[] typesInThisAssembly;

                    try
                    {
                        typesInThisAssembly = assembly.GetTypes();
                    }
                    catch (ReflectionTypeLoadException ex)
                    {
                        typesInThisAssembly = ex.Types;
                    }

                    if (typesInThisAssembly.IsNullOrEmpty())
                    {
                        continue;
                    }

                    allTypes.AddRange(typesInThisAssembly.Where(type => type != null));
                }
                catch (Exception ex)
                {
                    Logger.Warn(ex.ToString(), ex);
                }
            }

            return allTypes;
        }
    }
}
